/***************************************************************************
         MetaDataList.h  -  list with meta data objects
                             -------------------
    begin                : Sat Mar 06 2010
    copyright            : (C) 2010 by Thomas Eschenbacher
    email                : Thomas.Eschenbacher@gmx.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef META_DATA_LIST_H
#define META_DATA_LIST_H

#include "config.h"

#include <QtGlobal>
#include <QList>
#include <QMap>
#include <QMapIterator>
#include <QMutableMapIterator>
#include <QString>
#include <QVariant>

#include "libkwave/MetaData.h"
#include "libkwave/Sample.h"

namespace Kwave
{

    class Q_DECL_EXPORT MetaDataList: public QMap<QString, MetaData>
    {
    public:

	/** const iterator for the meta data list */
	typedef QMapIterator<QString, MetaData> Iterator;

	/** mutable iterator for the meta data list */
	typedef QMutableMapIterator<QString, MetaData> MutableIterator;

	/** Default constructor */
	MetaDataList();

	/**
	 * Constructor, creates a meta data list with only one single meta
	 * data item. In some cases you need to pass a meta data list to a
	 * function but you have only a single meta data item, so this might
	 * be quite handy
	 * @param meta const reference to a single meta data item
	 */
	explicit MetaDataList(const MetaData &meta);

	/** Destructor */
	virtual ~MetaDataList();

	/**
	 * Create a simple list of meta data items, sorted by the position
	 * of the first sample. All meta data items that do not correspond
	 * to a position or a "first" sample are mapped to the start (zero).
	 * @return a QList of meta data, sorted by position
	 */
	virtual QList<Kwave::MetaData> toSortedList() const;

	/**
	 * select elements from the meta data list that have the standard
	 * property STDPROP_TYPE set to a specific value.
	 *
	 * @param type the type to select @see Kwave::MetaData::STDPROP_TYPE
	 * @return list with found meta data objects
	 */
	virtual MetaDataList selectByType(const QString &type) const;

	/**
	 * select elements from the meta data list that overlap a given
	 * range of samples (selects elements with scope "Range" as well
	 * as elements with scope "Position")
	 *
	 * @param first index of the first sample
	 * @param last index of the last sample
	 * @return list with found meta data objects
	 */
	virtual MetaDataList selectByRange(
	    sample_index_t first, sample_index_t last) const;

	/**
	 * select elements from the meta data list that are exactly at a
	 * given position.
	 *
	 * @param pos index of the sample to select
	 * @return list with found meta data objects
	 */
	virtual MetaDataList selectByPosition(sample_index_t pos) const;

	/**
	 * select elements from the meta data list that contain a given
	 * property.
	 *
	 * @param property the property to search for
	 * @return list with found meta data objects
	 */
	virtual MetaDataList selectByProperty(const QString &property) const;

	/**
	 * select elements from the meta data list that contain a given
	 * property and a given value
	 *
	 * @param property the property to search for
	 * @param value the value that the property should have
	 * @return list with found meta data objects
	 */
	virtual MetaDataList selectByValue(
	    const QString &property, QVariant value) const;

	/**
	 * Checks whether a meta data object is contained in this list,
	 * the check is based on the unique id of the meta data object.
	 *
	 * @param metadata the object to search
	 * @return true if found, otherwise false
	 */
	virtual bool contains(const MetaData &metadata) const;

	/**
	 * Replaces all meta data objects that have the same type as one
	 * of the objects in the passed list with newer versions. If an
	 * object did not exist, it will be created. If an object is not
	 * in the passed list, it will be deleted.
	 *
	 * @param list listof meta data objects that should be replaced
	 * @note affects only objects with a type that was found in the
	 *       passed list
	 */
	virtual void replace(const MetaDataList &list);

	/**
	 * Adds a single meta data object to the list. If it is already
	 * present, the old version will be silently replaced.
	 * If the object is a null object and an object with the same
	 * ID exists in the list, this will work as remove().
	 *
	 * @param metadata the meta data object that should be added
	 */
	virtual void add(const MetaData &metadata);

	/**
	 * Adds a list of meta data objects to the list. Old versions of
	 * existing objects will be silently replaced.
	 *
	 * @param list list of meta data objects that should be added
	 */
	virtual void add(const MetaDataList &list);

	/**
	 * Removes one meta data object from the list (if it exists).
	 *
	 * @param metadata the object that should be removed
	 */
	virtual void remove(const MetaData &metadata);

	/**
	 * Removes a list of meta data objects from this list (if they exist).
	 *
	 * @param list the list of meta data objects to remove
	 */
	virtual void remove(const MetaDataList &list);

	/**
	 * Crops this list to a given range of samples. All position aware
	 * elements that are not covered by the given range will be removed,
	 * all covered elements will be adjusted.
	 *
	 * @param first index of the first sample
	 * @param last  index of the last sample
	 */
	virtual void cropByRange(sample_index_t first, sample_index_t last);

	/**
	 * copy elements from the meta data list that overlap a given
	 * range of samples (selects elements with scope "Range" as well
	 * as elements with scope "Position")
	 *
	 * @param offset index of the first sample
	 * @param length number of samples of the range
	 * @return list with a copy of found meta data objects
	 */
	virtual MetaDataList copy(
	    sample_index_t offset,
	    sample_index_t length
	) const;

	/**
	 * delete elements from the meta data list that overlap a given
	 * range of samples (selects elements with scope "Range" as well
	 * as elements with scope "Position") and have a binding to a
	 * track.
	 *
	 * @param offset index of the first sample
	 * @param length number of samples to delete
	 */
	virtual void deleteRange(sample_index_t offset, sample_index_t length);

	/**
	 * shift the positions or start/end of all elements that are after
	 * a given offset to the left.
	 *
	 * @param offset index of the first sample
	 * @param shift number of samples to shift left
	 */
	virtual void shiftLeft(sample_index_t offset, sample_index_t shift);

	/**
	 * shift the positions or start/end of all elements that are after
	 * a given offset to the right.
	 *
	 * @param offset index of the first sample
	 * @param shift number of samples to shift right
	 */
	virtual void shiftRight(sample_index_t offset, sample_index_t shift);

	/**
	 * scale the positions or start/end of all elements by a given factor
	 *
	 * @param scale the factor that is applied to all positions
	 */
	virtual void scalePositions(double scale);

	/** dump all meta data to stdout (for debugging) */
	virtual void dump() const;

    };

}

#endif /* META_DATA_LIST_H */

//***************************************************************************
//***************************************************************************
